package com.yum.lang;

import java.lang.annotation.Native;
import java.util.List;

/**
 * Created on 2023/5/25
 *
 * @Time 10:38
 * @Program YunMap
 * @Author YoHaNe/XiaoShuai
 */
public class YInteger extends YNumber implements Comparable<YInteger> {
    private static final long serialVersionUID = -4145431670973045339L;

    @Native
    public static final int MIN_VALUE = 0x80000000;

    @Native
    public static final int MAX_VALUE = 0x7fffffff;

    private final int value;

    final static int[] sizeTable = {9,99,999,9999,99999,999999,9999999,99999999,999999999,MAX_VALUE};

    //这个来确定两位索引的最后一位的字符数组
    //r = 36
    //index 36 = 6
    final static char [] DigitOnes = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    } ;

    //确认倒数第二位的数字
    //r = 36
    //index 36 = 3
    final static char [] DigitTens = {
            '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
            '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
            '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
            '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
            '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
            '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
            '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
            '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
            '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
            '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
    } ;

    final static char[] digits = {
            '0' , '1' , '2' , '3' , '4' , '5' ,
            '6' , '7' , '8' , '9' , 'a' , 'b' ,
            'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
            'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
            'o' , 'p' , 'q' , 'r' , 's' , 't' ,
            'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };

    public YInteger(int value) {
        this.value = value;
    }

    public YInteger(String value){
        this.value = parseInt(value,10);
    }


    /**
     * 若取值范围为-128 到 127 之间则调用YIntegerCache里面缓存的值
     * 否则新建一个新的对象返回
     * 在使用 Integer val = 2 时会自动调用valueOf()函数
     * @param value val
     * @return val
     */
    public static YInteger valueOf(int value){
        if( value <= YIntegerCache.HIGH && value >= YIntegerCache.LOW)
            return YIntegerCache.cache[value + (-YIntegerCache.LOW)];
        return new YInteger(value);
    }

    public static YInteger valueOf(String value){
        return YInteger.valueOf(parseInt(value,10));
    }


    public static int parseInt(String value){
        return parseInt(value,10);
    }


    /**
     * 字符串转int
     * @param value val
     * @param radix 基数
     * @return val(int)
     */
    public static int parseInt(String value,int radix){
        if(value == null)
            throw new NullPointerException("value is null!");
        //判断radix(基数,进制)是否在2到36之间
        if(radix < YCharacter.MIN_RADIX)
            throw new NumberFormatException("radix" + radix + "less than YCharacter.MIN.RADIX");
        if(radix > YCharacter.MAX_RADIX)
            throw new NumberFormatException("radix" + radix + "greater than YCharacter.MAX.RADIX");

        int result = 0;
        //判断是否为负数
        boolean negative = false;
        int i = 0,len = value.length();
        int limit = -MAX_VALUE;
        //multimin 判断在添加下一位数字前判断是否溢出
        //digit 当前要追加的数字
        int multmin,digit;

        if(len > 0){
            char firstChar = value.charAt(0);
            if(firstChar < '0'){
                if(firstChar == '-'){
                    negative = true;
                    limit = MIN_VALUE;
                }else if(firstChar != '+')
                    throw new NumberFormatException();
                if(len == 1)
                    throw new NumberFormatException();
                i++;
            }
            multmin = limit / radix;
            while (i < len){
                digit = Character.digit(value.charAt(i++),radix);
                if(digit < 0)
                    throw new NumberFormatException();
                if(result < multmin)
                    throw new NumberFormatException();
                result *= radix;
                if(result < limit + digit)
                    throw new NumberFormatException();
                result -= digit;
            }
        }else
            throw new NumberFormatException();
        return negative ? result : -result;
    }

    @Override
    public String toString() {
        return toString(value);
    }


    /**
     * toString
     * @param value value
     * @return value(String)
     */
    public static String toString(int value){
        if(value == MIN_VALUE)
            return "-2147483648";
        //检查长度，若为负数则长度要加一
        int size = value < 0 ? strSize(-value) + 1 : strSize(value);
        char[] buf = new char[size];
        getChars(value,size,buf);
        return new String(buf);
    }

    /**
     * 判断是几位数
     * @param x x
     * @return x.length
     */
    static int strSize(int x){
        for(int i=0;;i++){
            if(x < sizeTable[i])
                return i+1;
        }
    }

    /**
     * 将int转为string
     * @param i value
     * @param index size
     * @param buf char[]
     */
    static void getChars(int i,int index,char[] buf){
        int q,r;
        int charPos = index;
        char sign = 0;
        if(i < 0){
            sign = '-';
            i = -i;
        }
        //每次迭代生成后两位数字
        while (i >= 65536){
            //若 i = 65536 q = 655
            q = i / 100;
            //(q<<6)+(q<<5)+(q<<2) = q*64 + q*32 + q*4 = q * 100;
            //r = i - ( q * 100 ) = 65536 - 65500 = 36
            r = i - ((q << 6) + (q << 5) + (q << 2));
            //i = 655
            i = q;
            buf[--charPos] = DigitOnes[r];
            buf[--charPos] = DigitTens[r];
        }
        //buf = [null,null,null,3,6];
        do {
            //first : q = (655 * 52429) >>> 19 = 65 Now:buf = [null,null,null,3,6]
            //second : q = (65 * 52429) >>> 19 = 6 Now:buf = [null,null,5,3,6]
            //third : q = (6 * 52429) >>> 19 = 0 Now:buf = [null,5,5,3,6]
            q = (i * 52429) >>> (16 + 3);
            //first : r = i - (q * 10) = 655 - 650 = 5
            //second : r = 65 - 60 = 5
            //third : r = 6 - 0 = 6
            r = i - ((q << 3) + (q << 1));
            buf[--charPos] = digits[r];
            //first : i = 65
            //second : i = 6
            //third : i = 0 break;
            i = q;
        } while (i != 0);
        //finish Now:buf = [6,5,5,3,6]
        if(sign != 0){
            buf[--charPos] = sign;
        }
    }

    /**
     * 将高位的几位补到低位 如:rotateLeft(8,16)
     * 8 = 0000 0000 0000 0000 0000 0000 0000 1000
     * 前面16位和低位16位互换
     * result : 0000 0000 0000 1000 0000 0000 0000 0000 = 1,048,576
     * @param i val
     * @param distance 多少位
     * @return val
     */
    public static int rotateLeft(int i,int distance){
        //i = 123456789 distance = 8
        //i = 0000 0111 0101 1011 1100 1101 0001 0101
        // i << 8 = 0111 0101 1011 1100 1101 0001 0101 0000 0000
        // i >>> -8 = 0000 0000 0000 000 0000 0000 0000 0111
        // 0111 0101 1011 1100 1101 0001 0101 0000 0000 | 0000 0000 0000 000 0000 0000 0000 0111
        // 0111 0101 1011 1100 1101 0001 0101 0000 0111 = 31,604,937,991
        return (i << distance) | (i >>> -distance);
    }

    /**
     * 将低位的几位补到高位
     * @param i val
     * @param distance 多少位
     * @return val
     */
    public static int rotateRight(int i,int distance){
        /*
            例如：i=987654321, distance=3
            i                                       0011 1010 1101 1110 0110 1000 1011 0001
            i >>> distance                          0000 0111 0101 1011 1100 1101 0001 0110
            i << -distance                          0010 0000 0000 0000 0000 0000 0000 0000
            (i >>> distance) | (i << -distance)     0010 0111 0101 1011 1100 1101 0001 0110
         */
        return (i >>> distance) | (i << -distance);
    }


    /**
     * YIntegerCache 缓存类 存放 -128 到 127的缓存值
     */
    private static class YIntegerCache{
        static final int LOW = -128;
        static final int HIGH;
        static final YInteger cache[];
        static {
            int h = 127;
            String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if(integerCacheHighPropValue != null){
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i,127);
                    h = Math.min(i,MAX_VALUE - (-LOW) - 1);
                }catch (NumberFormatException e){
                    e.printStackTrace();
                }
            }
            HIGH = h;
            cache = new YInteger[(HIGH - LOW) + 1];
            int j = LOW;
            for(int k=0;k < cache.length;k++)
                cache[k] = new YInteger(j++);
            assert HIGH >= 127;
        }
        private YIntegerCache(){}
    }

    @Override
    public int compareTo(YInteger anotherInteger){
        return compare(this.value,anotherInteger.value);
    }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof YInteger)
            return value == ((YInteger) obj).intValue();
        return false;
    }

    @SuppressWarnings("all")
    public static int compare(int x,int y){
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }


    @Override
    public int intValue() {
        return value;
    }

    @Override
    public long longValue() {
        return (long)value;
    }

    @Override
    public double doubleValue() {
        return (double) value;
    }

    @Override
    public float floatValue() {
        return (float) value;
    }


}
